// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="FQLQuery.cs" company="">
//   
// </copyright>
// <summary>
//   Defines the FQLQuery type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace Facebook.Fluent
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Facebook.Fluent.Fields;

    /// <summary>
    /// Fluent API for create FQL queries.
    /// </summary>
    public class FQLQuery
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="FQLQuery"/> class.
        /// </summary>
        public FQLQuery()
        {
            this.Query = new StringBuilder();
        }

        /// <summary>
        /// Gets or sets the query.
        /// </summary>
        /// <value>The query.</value>
        private StringBuilder Query { get; set; }

        /// <summary>
        /// Adds the select part of the query..
        /// </summary>
        /// <typeparam name="T">Type of fields to select.</typeparam>
        /// <param name="fields">The fields to select.</param>
        public void AddSelect<T>(T[] fields)
        {
            this.Query.Append("select ");

            List<T> userFields = fields.ToList();
            userFields.Sort((x, y) => Enum.GetName(typeof(User), x).CompareTo(Enum.GetName(typeof(User), y)));
            for (int i = 0; i < userFields.Count; i++)
            {
                this.Query.Append(userFields[i]);
                if (i < userFields.Count - 1)
                {
                    this.Query.Append(", ");
                }
            }
        }

        /// <summary>
        /// Adds the from part of he query..
        /// </summary>
        /// <param name="name">The table name to select from.</param>
        public void AddFrom(string name)
        {
            this.Query.Append(" from ");
            this.Query.Append(name);
            this.Query.Append(" ");
        }

        /// <summary>
        /// Adds the where part of the query.
        /// </summary>
        /// <typeparam name="T">The type of field to perform comparison on.</typeparam>
        /// <param name="field">The field to compare with.</param>
        public void AddWhere<T>(T field)
        {
            this.Query.Append(" where ");
            this.Query.Append(field);
            this.Query.Append(" ");
        }

        /// <summary>
        /// Adds the comparison part of the query for a where block.
        /// </summary>
        /// <param name="op">The operator.</param>
        /// <param name="value">The value to compare against.</param>
        public void AddComparison(string op, object value)
        {
            this.Query.Append(String.Format(" {0} ", op));
            this.Query.Append(value);
            this.Query.Append(" ");
        }

        /// <summary>
        /// Gets the query as a string..
        /// </summary>
        /// <returns>the FQL query as a string.</returns>
        public string GetQuery()
        {
            return this.Query.ToString();
        }

        /// <summary>
        /// Adds the and part of the query.
        /// </summary>
        /// <param name="field">The field to AND with.</param>
        public void AddAnd(object field)
        {
            this.Query.Append(" and ");
            this.Query.Append(field);
            this.Query.Append(" ");
        }

        /// <summary>
        /// Adds the in part of the query.
        /// </summary>
        /// <param name="query">The subquery to IN with.</param>
        public void AddIn(FQLQuery query)
        {
            this.Query.Append(" in ( ");
            this.Query.Append(query.Query);
            this.Query.Append(" ) ");
        }
    }
}